﻿using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Transactions;
using System.Xml.Linq;
using T.FAS.Runtime.Action.Dao;
using T.FAS.Runtime.Metadata.Entity;
//using T.FAS.Authority.MetaData.Dev.Plugin;
//using T.FAS.Authority.MetaData.Entity;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Metadata.SPI;

namespace T.FAS.Runtime.Action.Plugin
{
    public class ActionMetaDataManager : AbsMetaDataManager, IMetaDataManager
    {
        ActionMetaDataLogic amdLogic = new ActionMetaDataLogic();
        ActionMetaDataMethodLogic methodLogic = new ActionMetaDataMethodLogic();
        ActionMetaDataMethodParamLogic paramLogic = new ActionMetaDataMethodParamLogic();
        //ActionACLLogic aclLogic = new ActionACLLogic();
        /// <summary>
        /// 新增Action元数据
        /// </summary>
        /// <param name="metaData"></param>
        public void Save(IMetaDataContent metaData)
        {
            ActionMetaData action = null;
            if (metaData != null && metaData is ActionMetaData)
            {
                action = metaData as ActionMetaData;
            }
            else
            {
                throw new ArgumentException("Action Save方法参数有错误，请检查");
            }
            if (!string.IsNullOrEmpty(metaData.MetaDataID) && !metaData.MetaDataID.Equals(action.ID, StringComparison.OrdinalIgnoreCase))
            {
                action.ID = metaData.MetaDataID;
            }
            //EntityTools.FillMainObjectFieldForAdd(action, metaData);

            if (action.Method != null)
            {
                action.Method.ID = Guid.NewGuid().ToString();
                action.Method.ActionMetaDataID = action.ID;
                //EntityTools.FillSystemFiledForAdd(action, metaData);
            }
            ArrayList methodParams = new ArrayList();

            if (action.MethodParams != null && action.MethodParams.Count > 0)
            {
                action.MethodParams.ForEach(p =>
                {
                    p.ID = Guid.NewGuid().ToString();
                    p.ActionMetaDataID = action.ID;
                    //EntityTools.FillSystemFiledForAdd(p, metaData);
                });
                methodParams.AddRange(action.MethodParams);
            }

            ArrayList aclDetails = new ArrayList();

            if (action.ActionACLDefine != null)
            {
                action.ActionACLDefine.ID = Guid.NewGuid().ToString();
                action.ActionACLDefine.ACLMetaDataType = ACLMetaDataType.Action;
                action.ActionACLDefine.ACLMetaDataID = action.ID;
                //EntityTools.FillSystemFiledForAdd(action.ActionACLDefine,metaData);
                if (action.ActionACLDefine.ACLDetails != null && action.ActionACLDefine.ACLDetails.Count > 0)
                {
                    action.ActionACLDefine.ACLDetails.ForEach(d =>
                    {
                        d.ID = Guid.NewGuid().ToString();
                        d.ACLDefineID = action.ActionACLDefine.ID;
                        //EntityTools.FillSystemFiledForAdd(d,metaData);
                    });
                    aclDetails.AddRange(action.ActionACLDefine.ACLDetails);
                }
            }
            try
            {
                //using (TransactionScope scope = new TransactionScope())
                //{
                if (!CheckUnique(metaData))
                {
                    throw new Exception($"不满足唯一性验证，Code:{action.Code}");
                }
                amdLogic.AddActionMetaData(action);
                //if (action.Method != null)
                //{
                //    methodLogic.AddActionMetaDataMethod(action.Method);
                //}
                //if (methodParams != null && methodParams.Count > 0)
                //{
                //    paramLogic.AddActionMetaDataMethodParamList(methodParams);
                //}
                //if (action.ActionACLDefine != null)
                //{
                //    aclLogic.AddACLDefine(action.ActionACLDefine);
                //    if (action.ActionACLDefine.ACLDetails != null && action.ActionACLDefine.ACLDetails.Count > 0)
                //    {
                //        aclLogic.AddACLDetailList(aclDetails);
                //    }
                //}
                //    scope.Complete();
                //}
            }
            catch (Exception e)
            {
                throw new Exception("元数据保存失败", e);
            }
        }
        /// <summary>
        /// 删除Action元数据
        /// </summary>
        /// <param name="metaData"></param>
        public void Delete(IMetaDataContent metaData)
        {
            if (metaData == null || string.IsNullOrEmpty(metaData.MetaDataID))
                throw new ArgumentNullException("IMetaDataContent", "metaData参数为空或MetadataID为空");
            try
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    amdLogic.DeleteActionMetaData(metaData.MetaDataID);
                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new Exception("Action元数据删除失败", e);
            }
        }
        /// <summary>
        /// 获取Action元数据
        /// </summary>
        /// <param name="metaDataId"></param>
        /// <returns></returns>
        public IMetaDataContent GetMetaDataContent(string metaDataId)
        {
            if (string.IsNullOrEmpty(metaDataId))
                throw new ArgumentNullException("metaDataId", "ActionID为空");
            var action = amdLogic.GetActionMetaDataByID(metaDataId);
            if (action != null)
            {
                //action.ActionACLDefine = aclLogic.GetACLDefineByActionID(action.ID);
                action.MetaDataID = action.ID;
                action.MetaDataCode = action.Code;
                action.MetaDataName = action.Name;
            }
            return action;
        }
        #region 基类方法

        public MetaDataCompileResult Compile(IList<IMetaDataContent> metadatas)
        {
            return new MetaDataCompileResult();
        }

        public ConflictMessage ConflictCheck(List<IMetaDataContent> releasedMetaData, IMetaDataContent releaseingMetaData)
        {
            return new ConflictMessage();
        }


        public IMetaDataContent DeserializeObject(string metaDataString, MetadataSerializeType serializeType)
        {
            if (serializeType == MetadataSerializeType.JSON)
            {
                var action = JsonConvert.DeserializeObject<ActionMetaData>(metaDataString);
                return action;
            }
            else
            {
                throw new NotImplementedException();
            }
        }


        public void Release(IMetaDataContent metaData, ReleaseStrategy releaseStrategy)
        {

        }

        public void Release(IMetaDataContent metaData)
        {

        }


        public string SerializeObject(IMetaDataContent metadata, MetadataSerializeType serializeType)
        {
            if (serializeType == MetadataSerializeType.JSON)
            {
                var action = metadata as ActionMetaData;

                if (!string.IsNullOrEmpty(metadata.MetaDataID) && !metadata.MetaDataID.Equals(action.ID))
                {
                    action.RefreshID(metadata.MetaDataID);
                }

                return JsonConvert.SerializeObject(action, new JsonSerializerSettings
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                });
            }
            else
            {
                throw new NotImplementedException();
            }
        }
        public void Update(IMetaDataContent metaData)
        {
            try
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    Delete(metaData);
                    Save(metaData);
                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new Exception($"Action元数据修改失败！\r\n元数据内容", e);
            }
        }

        public ValidateResult Validate(IMetaDataContent metaData)
        {
            return new ValidateResult();
        }

        public IList<MetaDataExportContent> Export(params IMetaDataContent[] metaDataList)
        {
            var contents = new List<MetaDataExportContent>();

            foreach (var item in metaDataList)
            {
                if (item is ActionMetaData action)
                {
                    /* Todo
                    if (action.ActionPermission?.DataPermissionObject != null)
                    {
                        TermDefinitionManager termDefinitionManager = new TermDefinitionManager();
                        action.ActionPermission.DataPermissionObject.TranslatedTerms = termDefinitionManager.GetMetaDataTerms(action.ActionPermission.DataPermissionObject.Id, action.ProjectBranchID);
                        if (action.ActionPermission.DataPermissionObject.DpoDetails?.Count > 0)
                        {
                            foreach (var dpoDetail in action.ActionPermission.DataPermissionObject.DpoDetails)
                            {
                                dpoDetail.TranslatedTerms = termDefinitionManager.GetMetaDataTerms(dpoDetail.DpdId, action.ProjectBranchID);
                            }
                        }
                    }
                    */
                    var exportContent = new MetaDataExportContent
                    {
                        Content = this.SerializeObject(action, MetadataSerializeType.JSON),
                        ExportType = MetaDataExportType.JSON,
                        MetaDataId = item.MetaDataID,
                        MetaDataCode = item.MetaDataCode,
                        MetaDataType = item.MetaData.MetaTypeID,
                        TenantID = item.MetaData.TenantId,
                    };
                    contents.Add(exportContent);
                }
            }
            return contents;
        }

        public void Import(IList<MetaDataExportContent> contents, MetaDataImportStrategy importStrategy)
        {
            if (contents == null || contents.Count < 1)
                return;
            if (importStrategy == MetaDataImportStrategy.Delete)
            {
                DeleteMetadata(contents);
            }
            else
            {
                ImportMetadata(contents);
            }
        }

        private void DeleteMetadata(IList<MetaDataExportContent> contents)
        {
            if (contents != null && contents.Count > 0)
            {
                try
                {
                    //ActionPermissionDefinitionManager permissionMgr = new ActionPermissionDefinitionManager();
                    using (var scope = new TransactionScope())
                    {
                        foreach (var content in contents)
                        {
                            //permissionMgr.Import(new ActionPermissionDefinitionForView { ActionID = content.MetaDataId }, MetaDataImportStrategy.Delete);
                            this.amdLogic.DeleteActionMetaData(content.MetaDataId);
                        }
                        scope.Complete();
                    }
                }
                catch (Exception ex)
                {
                    throw new FasException(ActionExceptionCode.MetadataExportError, $"元数据删除失败", ex);
                }
            }
        }

        private void ImportMetadata(IList<MetaDataExportContent> contents)
        {
            var list = new List<IMetaDataContent>();
            foreach (var exportContent in contents)
            {
                var content = this.DeserializeObject(exportContent.Content, MetadataSerializeType.JSON);
                var action = content as ActionMetaData;
                if (action != null && string.IsNullOrEmpty(action.ID))
                    action.ID = exportContent.MetaDataId;
                list.Add(action);
            }

            using (var scope = new TransactionScope())
            {
                this.Import(list);

                scope.Complete();
            }
        }

        private void Import(List<IMetaDataContent> metaDatas)
        {
            var actionList = new List<ActionMetaData>();
            foreach (var metaData in metaDatas)
            {
                var dataObject = metaData as ActionMetaData;
                if (dataObject == null)
                {
                    throw new FasException(ActionExceptionCode.ArgumentNullError, "元数据类型不是ActionMetaData, 实际类型:" + metaData.GetType().FullName);
                }

                actionList.Add(dataObject);
            }
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.Suppress))
                {
                    foreach (var action in actionList)
                    {
                        if (action.Method != null)
                        {
                            action.Method.ID = Guid.NewGuid().ToString();
                            action.Method.ActionMetaDataID = action.ID;
                            action.Method.CreateTime = DateTime.Now;
                            action.Method.LastModifyTime = DateTime.Now;
                            if (action.IsClientAction && !string.IsNullOrEmpty(action.Method.MethodContentForES5))
                            {
                                action.Method.MethodContent = action.Method.MethodContentForES5;
                            }
                            if (action.MethodParams != null)
                            {
                                action.MethodParams.ForEach
                                    (p =>
                                    {
                                        p.ID = Guid.NewGuid().ToString();
                                        p.ActionMetaDataID = action.ID;
                                        p.CreateTime = DateTime.Now;
                                        p.LastModifyTime = DateTime.Now;
                                    }
                                );
                            }
                        }
                        if (action.ActionACLDefine != null)
                        {
                            action.ActionACLDefine.ID = Guid.NewGuid().ToString();
                            if (action.ActionACLDefine.ACLDetails != null && action.ActionACLDefine.ACLDetails.Count > 0)
                            {
                                action.ActionACLDefine.ACLDetails.ForEach(d =>
                                {
                                    d.ID = Guid.NewGuid().ToString();
                                });
                            }
                        }
                        this.amdLogic.DeleteActionMetaData(action.ID);
                        this.amdLogic.AddActionMetaData(action);
                        /* Todo
                        //导入时调通权限的接口把Action上定义的权限控制信息导入到目标环境。
                        if (action.IsPermissionControl && action.ActionPermission != null)
                        {
                            if (string.IsNullOrEmpty(action.ActionPermission.ActionID))
                                action.ActionPermission.ActionID = action.ID;
                            if (action.ActionPermission.DataPermissionObject != null && action.ActionPermission.DataPermissionObject.DpoDetails != null)
                            {
                                action.ActionPermission.DataPermissionObject.DpoDetails.ForEach(d =>
                                {
                                    if (string.IsNullOrEmpty(d.DoId))
                                        d.DoId = action.ID;
                                });
                            }
                            action.ActionPermission.ActionType = "Action";
                            ActionPermissionDefinitionManager permissionMgr = new ActionPermissionDefinitionManager();
                            permissionMgr.Import(action.ActionPermission);
                        }
                        */
                    }

                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new FasException(ActionExceptionCode.MetadataExportError, "ActionMetaData元数据导入失败", e);
            }
        }

        public void Enable(params IMetaDataContent[] metaData)
        {

        }

        #region 元数据依赖相关

        /// <summary>
        /// 获取当前元数据依赖谁
        /// </summary>
        /// <param name="metaDataContent"></param>
        /// <returns></returns>
        public List<T.FAS.Runtime.Metadata.Entity.MetaDataDependency> GetMetaDataDependencys(IMetaDataContent metaDataContent)
        {
            return DependencyManager.GetMetaDataDependencys(metaDataContent);
        }
        /// <summary>
        /// 当前元数据变更需要通知出去的变更信息(MetaUpdateType定义的枚举项,需要在这里处理)
        /// </summary>
        /// <param name="oldMetaData"></param>
        /// <param name="newMetaData"></param>
        /// <returns></returns>
        public MetaDataUpdateSet GetMetaDataUpdateSet(IMetaDataContent oldMetaData, IMetaDataContent newMetaData)
        {
            return DependencyManager.GetMetaDataUpdateSet(oldMetaData, newMetaData);
        }
        /// <summary>
        /// 其他元数据变更通知到当前元数据,当前元数据对变更的响应逻辑
        /// </summary>
        /// <param name="metaDataContent"></param>
        /// <param name="updateSet"></param>
        /// <returns></returns>
        public MetaUpdateResult UpdateDependencyMetaData(IMetaDataContent metaDataContent, MetaDataUpdateSet updateSet)
        {
            return DependencyManager.UpdateDependencyMetaData(metaDataContent, updateSet);
        }

        #endregion

        #region 元数据依赖及国际化相关

        public IRefSchemaEntity BuildRefSchema(IMetaDataContent metaDataContent)
        {           
            if (metaDataContent is ActionMetaData act)
            {         
                ActionRefSchemaEntity refSchema = new ActionRefSchemaEntity
                {
                    ID = act.MetaDataID,
                    Code = act.MetaDataCode,
                    Name = act.MetaDataName,
                };
                if (act.MethodParams != null && act.MethodParams.Count > 0)
                {
                    refSchema.Params = new Dictionary<string, ActionRefSchemaEntity.Param>();
                    foreach (var par in act.MethodParams)
                    {
                        if (par != null && par.Code != null)
                            refSchema.Params[par.Code] = ActionRefSchemaEntity.Param.Mapping(act, par);
                    }
                }
                return refSchema;
            }
            else
            {
                throw new ArgumentNullException(nameof(metaDataContent));
            }
        }
        
        public IEnumerable<T.FAS.Runtime.Metadata.Entity.Term> BuildTerms(IMetaDataContent metaDataContent, IEnumerable<T.FAS.Runtime.Metadata.Entity.Term> termList = null)
        {
            return new List<T.FAS.Runtime.Metadata.Entity.Term>();
        }
        

        public IRefSchemaEntity DeserializeRefSchemaEntity(string schemaEntityJson)
        {
            return JsonConvert.DeserializeObject<ActionRefSchemaEntity>(schemaEntityJson);
        }

        ValidateResult IMetaDataManager.CompatibleValidate(IMetaDataContent metaData, IMetaDataContent oldMetaData)
        {
            return new ValidateResult { state = "1" };            
        }
        private string GetBasicType(string paramValueType)
        {
            switch (paramValueType)
            {
                case "String":
                    return "string";
                case "Int":
                case "Long":
                case "Decimal":
                    return "number";
                case "Date":
                case "Time":
                case "DateTime":
                    return "Date";
                case "Boolean":
                    return "boolean";
                default:
                    return "";
            }
        }
        public override MetaGenerateCodeResult GenerateCode(IMetaDataContent metadata, bool isInternational)
        {
            MetaGenerateCodeResult result = new MetaGenerateCodeResult();
            
            return result;
        }
        #endregion
        #endregion

    }
}
